#define _CRT_SECURE_NO_WARNINGS 1

#include"String.h"

namespace bit
{
	string::~string()
	{
		delete[] _str;
		_str = nullptr;
		_size = 0;
		_capacity = 0;
	}

	string::string(const char* str )
		:_size(strlen(str))
	{
		_capacity = _size;
		_str = new char[_size + 1];
		strcpy(_str, str);
	}

	string::string(const bit::string& s)
	{
		_str = new char[s._capacity + 1];
		_size = s._size;
		_capacity = s._capacity;
		memcpy(_str, s._str, _size + 1);
	}

	void string::push_back(const char c)
	{
		if (_size == _capacity)
		{
			reserve(_capacity > 0 ? 2 * _capacity : 4);
		}
		_str[_size++] = c;
		_str[_size] = '\0';
	}

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len >= _capacity)
		{
			reserve(std::max(_size + len, 2 * _capacity));
		}
		strcpy(_str + _size, str);
		_size += len;
	}

	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* tmp = new char[n];
			memcpy(tmp, _str, _size + 1);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}

	std::ostream& operator<<(std::ostream& _cout, bit::string& str)
	{
		for (auto ch : str)
		{
			_cout << ch;
		}

		return _cout;
	}

	std::istream& operator>>(std::istream& _cin, bit::string& str)
	{
		str.clear();
		char ch;
		ch = _cin.get();
		char arr[256];
		int i = 0;
		while (ch != '\n')
		{
			arr[i++] = ch;
			ch = _cin.get();
			if (i == 255)
			{
				str += arr;
				i = 0;
			}
		}

		arr[i] = '\0';
		str += arr;

		return _cin;
	}

	void swap(bit::string& a, bit::string& b)
	{
		a.swap(b);
	}

	void string::swap(bit::string& b)
	{
		char* c_str = this->_str;
		size_t c_size = this->_size;
		size_t c_capacity = this->_capacity;
		this->_str = b._str;
		this->_size = b._size;
		this->_capacity = b._capacity;
		b._str = c_str;
		b._size = c_size;
		b._capacity = c_capacity;
	}

	void string::insert(size_t pos, const char c)
	{
		assert(pos < _size);

		if (_size == _capacity)
		{
			reserve(_capacity > 0 ? 2 * _capacity : 4);
		}
		int end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			--end;
		}
		_str[pos] = c;
		++_size;
	}

	void string::insert(size_t pos, const char* str)
	{
		size_t len = strlen(str);
		if (_size + len >= _capacity)
		{
			reserve(std::max(_size + len, 2 * _capacity));
		}
		int end = _size + len;
		while (end > pos + len - 1)
		{
			_str[end] = _str[end - len];
			--end;
		}
		for (int i = 0; i < len; i++)
		{
			_str[pos + i] = str[i];
		}
		_size += len;
	}

	void string::resize(size_t n, char c)
	{
		if (n > _size)
		{
			if (n > _capacity)
			{
				reserve(std::max(n, _capacity * 2));
			}
			for (int i = _size; i < n; i++)
			{
				_str[i] = c;
			}
		}
		_str[n] = '\0';
		_size = n;
	}

	string string::substr(size_t pos, size_t len)const
	{
		assert(pos <= _size);
		if(pos+len<_size)
		{
			char* str = new char[len + 1];
			memcpy(str, _str + pos, len);
			str[len] = '\0';
			string tmp(str);
			delete[] str;
			return tmp;
		}
		else
		{
			char* str = new char[_size - pos + 1];
			memcpy(str, _str + pos, _size - pos + 1);
			string tmp(str);
			delete[] str;
			return tmp;
		}
	}

	string& string::operator=(const string& s)
	{
		reserve(s._capacity + 1);
		for (int i = 0; i <= s._size; i++)
		{
			_str[i] = s._str[i];
		}
		_size = s._size;
		return *this;
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);
		if (len > _size - pos)
		{
			_size = pos;
			_str[pos] = '\0';
			return;
		}
		for (int i = pos + len; i < _size; i++)
		{
			_str[pos + i - pos - len] = _str[i];
		}
		_size -= len;
		_str[_size] = '\0';
	}

	//const size_t string::npos = -1;

}